import { Message } from 'element-ui'

/**
 * [pick 从对象中取出特定项，返回新对象]
 * @Author   罗文
 * @DateTime 2018-09-28
 * @param    {[Object]}   obj        [目标对象]
 * @param    {[Array]}   filtersArr [要筛选的键数组]
 * @return   {[type]}              [description]
 */
export const pick = function(obj, keysArr) {
  let newObj = {}
  let keys = Object.keys(obj)

  keysArr.forEach(key => {
    let isInclude = keys.includes(key)
    if (isInclude) newObj[key] = obj[key]
  })

  return newObj
}

/**
 * [loadScript 动态加载js]
 * @param  {[String]}  url        [动态加载的script url]
 * @param  {Boolean} isAppendHead [是否append到head标签内]
 */
export const loadScript = function(url, isAppendHead = false) {
  if (!url) return

  return new Promise((resolve, reject) => {
    const scriptDom = document.createElement('script')
    scriptDom.setAttribute('src', url)
    scriptDom.setAttribute('type', 'text/javascript')
    document[isAppendHead ? 'head' : 'body'].appendChild(scriptDom)
    scriptDom.onload = () => {
      resolve('successful')
    }
    scriptDom.onerror = () => {
      resolve('failed')
    }
  })
}

/**
 * [isObject 判断一个对象是否是纯对象]
 * @param  {[type]}  obj [description]
 * @return {Boolean}     [description]
 */
export const isObject = function(obj) {
  return Object.prototype.toString.call(obj).includes('Object')
}

/**
 * [isClient 当前是否是在客户端运行]
 */
export const isClient = function() {
  return typeof window !== 'undefined'
}

/**
 * [getBuildEnv 获取当前打包或者api信息]
 * @return {[type]} [description]
 */
export const getBuildEnv = function() {
  //准备环境信息
  let buildEnv = {
    build: 'test', //用于接口代理  test - 接口代理到测试环境  cp-接口代理到tongkao100   production - 接口代理到tongkao100,静态资源引入cdn
    env: 'development' //用于打包代码的运行环境  development - 开发环境或不传   production - 测试环境或生产
  }

  // 可能有如下情况：
  // 1、 build:test  + env:development   - 运行在开发环境，接口或链接用测试环境
  // 2、 build:test  + env:production   - 运行在测试环境，接口或链接用测试环境
  // 3、 build:cp  + env:production   - 运行在预发布环境，接口或链接用生产环境
  // 4、 build:production  + env:production   - 运行在生产环境，接口或链接用生产环境
  try {
    //服务端直接取环境变量
    let options = process.env.BUILD_OPTIONS

    if (typeof options === 'string') {
      buildEnv = JSON.parse(options)
    } else if (isObject(options)) {
      buildEnv = options
    } else {
      throw new Error()
    }
  } catch (e) {}

  // isCpOrProd 判断是否是在cp或者生产环境
  buildEnv.isCpOrProd = ['cp', 'production'].includes(buildEnv.build)

  return buildEnv
}

/**
 * [isMobile 判断当前是不是移动端]
 * @return {[type]} [description]
 */
export const isMobile = function() {
  var userAgentInfo = navigator.userAgent
  return userAgentInfo.match(/(iPhone|iPod|iPad|Android|ios)/i)
}

/**
 * [isIE 是否是IE]
 * @return {[type]} [description]
 */
export const isIE = function() {
  return !!window.ActiveXObject || 'ActiveXObject' in window
}

/**
 * [isLowIE10 是否是IE9及以下版本]
 */
export const isLowIE10 = function() {
  if (
    navigator.appName === 'Microsoft Internet Explorer' &&
    parseInt(
      navigator.appVersion
        .split(';')[1]
        .replace(/[ ]/g, '')
        .replace('MSIE', '')
    ) < 10
  ) {
    return true
  } else {
    return false
  }
}

/**
 * 获取url参数
 * @param {string} query url参数
 * @return {object} url参数对象
 * @example
 * util.getQuery('lechebang.com?key=value&city=3')
 * util.getQuery(location.search)
 * // 如果参数里面有url或者中文，请先自行先encodeURIComponent字符串
 */
export const getQuery = function(query) {
  var ret = {}
  var searchReg = /([^&=?]+)=([^&]+)/g
  var name, value
  let match = searchReg.exec(query)

  while (match) {
    name = match[1]
    value = match[2]
    ret[name] = decodeURIComponent(value)
    match = searchReg.exec(query)
  }
  return ret
}

/**
 * 追加url参数
 * @param {string} url url参数
 * @param {string|object} key 名字或者对象
 * @param {string} value 值
 * @return {string} 返回新的url
 * @example
 * util.appendQuery('lechebang.com', 'id', 3);
 * util.appendQuery('lechebang.com?key=value', { cityId:2,cityName: '北京'});
 */
export const appendQuery = function(url, key, value) {
  var options = key
  var _this = this

  if (!key && !value) return url

  if (typeof options === 'string') {
    options = {}
    options[key] = value
  }

  options = param(options)

  if (url.includes('?')) {
    url += '&' + options
  } else {
    url = options ? url + '?' + options : url
  }

  function param(query, isEncode = true) {
    let params = []

    for (let i in query) {
      let cvalue = query[i]

      if (Object.prototype.toString.call(cvalue).includes('Object')) {
        cvalue = JSON.stringify(cvalue)
      }

      params.push(`${i}=${isEncode ? encodeURIComponent(cvalue) : cvalue}`)
    }

    return params.join('&')
  }

  return url
}

/**
 * [catchAndAlert 捕获promise错误并且界面提示errmsg]
 * @param  {[String]} errmsg [错误信息]
 */
export const catchAndAlert = function(errmsg) {
  if (isClient() && errmsg) Message.error(errmsg)
}

/**
 * [dateFormat 格式化时间]
 * @param  {[type]} )  [description]
 * @return {[type]}   [description]
 */
export const dateFormat = (function() {
  var dateFormat1 = function() {
    var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZWNC]|'[^']*'|'[^']*'/g
    var timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g
    var timezoneClip = /[^-+\dA-Z]/g

    // Regexes and supporting functions are cached through closure
    return function(date, mask, utc, gmt) {
      // You can't provide utc if you skip other args (use the 'UTC:' mask prefix)
      if (
        arguments.length === 1 &&
        kindOf(date) === 'string' &&
        !/\d/.test(date)
      ) {
        mask = date
        date = undefined
      }

      date = date || new Date()

      if (!(date instanceof Date)) {
        date = new Date(date)
      }

      if (isNaN(date)) {
        throw TypeError('Invalid date')
      }

      mask = String(
        dateFormat1.masks[mask] || mask || dateFormat1.masks['default']
      )

      // Allow setting the utc/gmt argument via the mask
      var maskSlice = mask.slice(0, 4)
      if (maskSlice === 'UTC:' || maskSlice === 'GMT:') {
        mask = mask.slice(4)
        utc = true
        if (maskSlice === 'GMT:') {
          gmt = true
        }
      }

      var _ = utc ? 'getUTC' : 'get'
      var d = date[_ + 'Date']()
      var D = date[_ + 'Day']()
      var m = date[_ + 'Month']()
      var y = date[_ + 'FullYear']()
      var H = date[_ + 'Hours']()
      var M = date[_ + 'Minutes']()
      var s = date[_ + 'Seconds']()
      var L = date[_ + 'Milliseconds']()
      var o = utc ? 0 : date.getTimezoneOffset()
      var W = getWeek(date)
      var N = getDayOfWeek(date)
      var flags = {
        d: d,
        dd: pad(d),
        ddd: dateFormat1.i18n.dayNames[D],
        dddd: dateFormat1.i18n.dayNames[D + 7],
        m: m + 1,
        mm: pad(m + 1),
        mmm: dateFormat1.i18n.monthNames[m],
        mmmm: dateFormat1.i18n.monthNames[m + 12],
        yy: String(y).slice(2),
        yyyy: y,
        h: H % 12 || 12,
        hh: pad(H % 12 || 12),
        H: H,
        HH: pad(H),
        M: M,
        MM: pad(M),
        s: s,
        ss: pad(s),
        l: pad(L, 3),
        L: pad(Math.round(L / 10)),
        t: H < 12 ? 'a' : 'p',
        tt: H < 12 ? 'am' : 'pm',
        T: H < 12 ? 'A' : 'P',
        TT: H < 12 ? 'AM' : 'PM',
        Z: gmt
          ? 'GMT'
          : utc
          ? 'UTC'
          : (String(date).match(timezone) || [''])
              .pop()
              .replace(timezoneClip, ''),
        o:
          (o > 0 ? '-' : '+') +
          pad(Math.floor(Math.abs(o) / 60) * 100 + (Math.abs(o) % 60), 4),
        S: ['th', 'st', 'nd', 'rd'][
          d % 10 > 3 ? 0 : (((d % 100) - (d % 10) !== 10) * d) % 10
        ],
        W: W,
        N: N,
        C: ['日', '一', '二', '三', '四', '五', '六', '日'][N]
      }

      return mask.replace(token, function(match) {
        if (match in flags) {
          return flags[match]
        }
        return match.slice(1, match.length - 1)
      })
    }
  }

  dateFormat1.masks = {
    default: 'ddd mmm dd yyyy HH:MM:ss',
    shortDate: 'm/d/yy',
    mediumDate: 'mmm d, yyyy',
    longDate: 'mmmm d, yyyy',
    fullDate: 'dddd, mmmm d, yyyy',
    shortTime: 'h:MM TT',
    mediumTime: 'h:MM:ss TT',
    longTime: 'h:MM:ss TT Z',
    isoDate: 'yyyy-mm-dd',
    isoTime: 'HH:MM:ss',
    isoDateTime: "yyyy-mm-dd'T'HH:MM:sso",
    isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'",
    expiresHeaderFormat: 'ddd, dd mmm yyyy HH:MM:ss Z'
  }

  // Internationalization strings
  dateFormat1.i18n = {
    dayNames: [
      'Sun',
      'Mon',
      'Tue',
      'Wed',
      'Thu',
      'Fri',
      'Sat',
      'Sunday',
      'Monday',
      'Tuesday',
      'Wednesday',
      'Thursday',
      'Friday',
      'Saturday'
    ],
    monthNames: [
      'Jan',
      'Feb',
      'Mar',
      'Apr',
      'May',
      'Jun',
      'Jul',
      'Aug',
      'Sep',
      'Oct',
      'Nov',
      'Dec',
      'January',
      'February',
      'March',
      'April',
      'May',
      'June',
      'July',
      'August',
      'September',
      'October',
      'November',
      'December'
    ]
  }

  function pad(val, len) {
    val = String(val)
    len = len || 2
    while (val.length < len) {
      val = '0' + val
    }
    return val
  }

  /**
   * Get the ISO 8601 week number
   * Based on comments from
   * http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html
   *
   * @param  {Object} `date`
   * @return {Number}
   */
  function getWeek(date) {
    // Remove time components of date
    var targetThursday = new Date(
      date.getFullYear(),
      date.getMonth(),
      date.getDate()
    )

    // Change date to Thursday same week
    targetThursday.setDate(
      targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3
    )

    // Take January 4th as it is always in week 1 (see ISO 8601)
    var firstThursday = new Date(targetThursday.getFullYear(), 0, 4)

    // Change date to Thursday same week
    firstThursday.setDate(
      firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3
    )

    // Check if daylight-saving-time-switch occured and correct for it
    var ds =
      targetThursday.getTimezoneOffset() - firstThursday.getTimezoneOffset()
    targetThursday.setHours(targetThursday.getHours() - ds)

    // Number of weeks between target Thursday and first Thursday
    var weekDiff = (targetThursday - firstThursday) / (86400000 * 7)
    return 1 + Math.floor(weekDiff)
  }

  /**
   * Get ISO-8601 numeric representation of the day of the week
   * 1 (for Monday) through 7 (for Sunday)
   *
   * @param  {Object} `date`
   * @return {Number}
   */
  function getDayOfWeek(date) {
    var dow = date.getDay()
    if (dow === 0) {
      dow = 7
    }
    return dow
  }

  /**
   * kind-of 判断一个变量的类型
   * @param  {*} val
   * @return {String}
   */
  function kindOf(val) {
    if (val === null) {
      return 'null'
    }

    if (val === undefined) {
      return 'undefined'
    }

    if (typeof val !== 'object') {
      return typeof val
    }

    if (Array.isArray(val)) {
      return 'array'
    }

    return {}.toString
      .call(val)
      .slice(8, -1)
      .toLowerCase()
  }
  return dateFormat1()
})()
